--
-- @Author:      name
-- @DateTime:    2018-03-30 23:05:48
-- @Description: 消息的处理
local skynet = require "skynet"
local log = require "Logger"
local redis = require "skynet.db.redis"

local maxconn = 2 --最大连接数
local MessageHandler = class("MessageHandler")

---------------------------------------------------------
-- Private
---------------------------------------------------------
function MessageHandler:ctor(message_dispatch)
	self.pool = {} --连接池
	self.maxconn = 1
	self.message_dispatch = message_dispatch
	self:register()
end

--注册本服务里的消息
function MessageHandler:register()
	local tbMessage = {
		"start",
		"set",
		"get",
		"hmset",
		"hincrby",
		"hmget",
		"hset",
		"hget",
		"hgetall",
		"zadd",
		"keys",
		"zrange",
		"zrevrange",
		"zrank",
		"zrevrank",
		"zscore",
		"zcount",
		"zcard",
		"incr",
		"del",
		"exists",
		"lindex",
		"llen",
		"lpop",
		"lpush",
		"lrange",
		"lrem",
		"lset",
		"rpop",
		"rpush",
		"expire",
	}
	for k,v in pairs(tbMessage) do 
		self.message_dispatch:registerSelf(v, handler(self,self[v]))
	end

end


--从连接池里取一个服务
function MessageHandler:getConnect(uid)
	local db
	if not uid or self.maxconn == 1 then
		db = self.pool[1]
	else
		db = self.pool[uid % self.maxconn]
	end
	return db
end

--连接断开情况下，定时发消息，失败socketchannel.lua 会进行重连
function MessageHandler:heartbeat()
	local function queryFunc(db_service)
		return db_service:set("heartbeat",os.time())   
	end	
    skynet.fork(function ()
        while true do
        	skynet.sleep(100*5) --100=1秒
            for k,db in pairs(self.pool) do
            	local status, res = pcall(queryFunc, db)  
            	if not status then --发送消息失败 socketchannel 会自动重连
            		print("###发送数据到redis失败, 自动重连。。。")
            	end
            end            
        end
    end)
end
---------------------------------------------------------
-- CMD
---------------------------------------------------------

function MessageHandler:start()
	self.maxconn = tonumber(skynet.getenv("redis_maxinst")) or maxconn
	local host
	local port
	local db_id = 0 --对应的库id
	local auth
	for i = 1, self.maxconn do
		host = skynet.getenv("redis_host" .. i)
		port = skynet.getenv("redis_port" .. i)
		auth = skynet.getenv("redis_auth" .. i)
		db_id = skynet.getenv("redis_dbid" .. i) or 0
		if auth == '' then
			auth = nil
		end
		-- print("____redis connect___________",host,port,db,auth)
		local db = redis.connect({
			host = host,
			port = port,
			db = db_id,
			auth = auth,
		})
		if db then
			--db:flushdb() --测试期，清理redis数据
			-- print("______db__",db)
			table.insert(self.pool, db)
		else
			log.error("redis 连接错误____")
		end
	end
	self:heartbeat()
end

--设置 key 
function MessageHandler:set(uid, key, value)
	local db = self:getConnect(uid)
	local retsult = db:set(key,value)
	
	return retsult
end

--取 key
function MessageHandler:get(uid, key)
	local db = self:getConnect(uid)
	local retsult = db:get(key)
	
	return retsult
end

--设置 hash
function MessageHandler:hmset(uid, key, t)
	local data = {}
	for k, v in pairs(t) do
		table.insert(data, k)
		table.insert(data, v)
	end

	local db = self:getConnect(uid)
	local result = db:hmset(key, table.unpack(data))

	return result
end

--增量加减
function MessageHandler:hincrby(uid, key, value, num)
	local db = self:getConnect(uid)
	local result = db:hincrby(key, value, num)	
	return result
end

--取 hash map
function MessageHandler:hmget(uid, key, ...)
	if not key then return end
	print(...)
	local db = self:getConnect(uid)
	local result = db:hmget(key, ...)
	
	return result
end

--设置 hash
function MessageHandler:hset(uid, key, filed, value)
	local db = self:getConnect(uid)
	local result = db:hset(key,filed,value)
	
	return result
end

-- 获取存储在哈希表中指定字段的值。
function MessageHandler:hget(uid, key, filed)
	local db = self:getConnect(uid)
	local result = db:hget(key, filed)
	
	return result
end

-- 返回哈希表中，所有的字段和值
function MessageHandler:hgetall(uid, key)
	local db = self:getConnect(uid)
	local result = db:hgetall(key)
	
	return result
end

-----------------集合start

-- 向有序集合添加一个或多个成员，或者更新已存在成员的分数
function MessageHandler:zadd(uid, key, score, member)
	local db = self:getConnect(uid)
	local result = db:zadd(key, score, member)

	return result
end

-- 查找所有符合给定模式( pattern)的 key 。
function MessageHandler:keys(uid, key)
	local db = self:getConnect(uid)
	local result = db:keys(key)
	return result
end

-- 通过索引区间返回有序集合成指定区间内的成员
function MessageHandler:zrange(uid, key, from, to)
	local db = self:getConnect(uid)
	local result = db:zrange(key, from, to)

	return result
end

-- 返回有序集中指定区间内的成员，通过索引，分数从高到底
function MessageHandler:zrevrange(uid, key, from, to ,scores)
	local result
	local db = self:getConnect(uid)
	if not scores then
		result = db:zrevrange(key,from,to)
	else
		result = db:zrevrange(key,from,to,scores)
	end
	
	return result
end

-- 返回有序集合中指定成员的索引
function MessageHandler:zrank(uid, key, member)
	local db = self:getConnect(uid)
	local result = db:zrank(key,member)

	return result
end

-- 返回有序集合中指定成员的排名，有序集成员按分数值递减(从大到小)排序
function MessageHandler:zrevrank(uid, key, member)
	local db = self:getConnect(uid)
	local result = db:zrevrank(key,member)

	return result
end

-- 返回有序集中，成员的分数值
function MessageHandler:zscore(uid, key, score)
	local db = self:getConnect(uid)
	local result = db:zscore(key,score)

	return result
end

-- 计算在有序集合中指定区间分数的成员数
function MessageHandler:zcount(uid, key, from, to)
	local db = self:getConnect(uid)
	local result = db:zcount(key,from,to)

	return result
end

-- 获取有序集合的成员数
function MessageHandler:zcard(uid, key)
	local db = self:getConnect(uid)
	local result = db:zcard(key)
	return result
end

-----------------集合end

-- 对key的数值加1
function MessageHandler:incr(uid, key)
	local db = self:getConnect(uid)
	local result = db:incr(key)
	
	return result
end

-- 删除key
function MessageHandler:del(uid, key)
	local db = self:getConnect(uid)
	local result = db:del(key)	
	return result
end

-- key是否存在
function MessageHandler:exists(uid, key)
	local db = self:getConnect(uid)
	local result = db:exists(key)
	
	return result
end

-----------------列表start

-- 通过索引获取列表中的元素
function MessageHandler:lindex(uid, key, index)
	local db = self:getConnect(uid)
	local result = db:lindex(key, index)	
	return result
end

-- 获取列表长度
function MessageHandler:llen(uid, key)
	local db = self:getConnect(uid)
	local result = db:llen(key)	
	return result
end

-- 移出并获取列表的第一个元素
function MessageHandler:lpop(uid, key)
	local db = self:getConnect(uid)
	local result = db:lpop(key)	
	return result
end

-- 将一个或多个值插入到列表头部
function MessageHandler:lpush(uid, key, value)
	local db = self:getConnect(uid)
	local result = db:lpush(key, value)	
	return result
end

-- 获取列表指定范围内的元素
function MessageHandler:lrange(uid, key, start, stop)
	local db = self:getConnect(uid)	
	local result = db:lrange(key, start, stop)
	return result
end

-- 移除列表元素
-- count > 0 : 从表头开始向表尾搜索，移除与 VALUE 相等的元素，数量为 COUNT 。
-- count < 0 : 从表尾开始向表头搜索，移除与 VALUE 相等的元素，数量为 COUNT 的绝对值。
-- count = 0 : 移除表中所有与 VALUE 相等的值。
function MessageHandler:lrem(uid, key, value, count)
	local db = self:getConnect(uid)
	local count = count or 0 
	local result = db:lrem(key, value, count)	
	return result
end

-- 通过索引设置列表元素的值
function MessageHandler:lset(uid, key, index, value)
	local db = self:getConnect(uid)
	local result = db:lset(key, index, value)	
	return result
end

-- 移除列表的最后一个元素，返回值为移除的元素。
function MessageHandler:rpop(uid, key)
	local db = self:getConnect(uid)
	local result = db:rpop(key)	
	return result
end

-- 在列表中添加一个或多个值
function MessageHandler:rpush(uid, key, value)
	local db = self:getConnect(uid)
	local result = db:rpush(key,value)
	return result
end

-----------------列表end

-- 给key设置过期时间
function MessageHandler:expire(uid, key, value)
	local db = self:getConnect(uid)
	local result = db:expire(key,value)
	return result
end

return MessageHandler